#include <stdlib.h>
#include "Image.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>


// imInit initialise dimx et dimy (après vérification) de la structure Image
// puis alloue le tableau de pixel dans le tas
void imInit(image * im , int x, int y)
{
    assert(x>0 && y>0);
    assert(im!=NULL);
    im->dimx=x;
    im->dimy=y;
    im->tab= (pixel*)malloc(x*y*(sizeof(pixel)));
}




// Libère la mémoire du tableau de pixels et met les
// champs dimx et dimy de la structure à 0
void imLibere(image * im)
{
    free(im->tab);
    im->dimx=0;
    im->dimy=0;

}



// imCreer alloue dans le tas une structure Image puis l'initialise
// avec imInit => 2 lignes

image *imCreer(int dimx, int dimy)
{
    image * im;
    im = malloc(sizeof(image));
    imInit(im,  dimx,  dimy);
    return im;
}


// Libere le tableau de pixel en appelant imLibere puis détruit
// la structure image

void imDetruire(image  ** pim)
{
    imLibere(*pim);
    free(pim);
    *pim=NULL;

}


// getPix récupère le pixel de coordonnée (x,y) en vérifiant leur validité
// la formule pour passer de 2D à un tab 1D est  pix[y*dimx+x]

pixel* getpix(image im, int x, int y)
{
    assert(x>=0 && x<(im.dimx));
    assert(y>=0 && y<(im.dimy));
    return &im.tab[y*im.dimx+x];
}

pixel Constgetpix(image im, int x, int y)
{
    assert(x>=0 && x<(im.dimx));
    assert(y>=0 && y<(im.dimy));
    return im.tab[y*im.dimx+x];
}

// setPix modifie le pixel de coord (x,y)

void setPix(image * im, int x, int y, pixel couleur)
{
    pixel* pix;

    pix = getpix(*im, x , y);
    pix->r = couleur.r;
    pix->g = couleur.g;
    pix->b = couleur.b;



}


// dessine un rectangle de couleur dans l'image en utilisant setPix

void imDessineRect(image * im, int Xmin,int Ymin, int Xmax, int Ymax, pixel couleur)
{
int i,j;
    for(i=Xmin;i<Xmax;i++)
    {
        for(j=Ymin;j<Ymax;j++)
        {
        setPix(im,i,j,couleur);
        }
    }


}

// efface l'image en appelant imDessineRectangle avec le bon rectangle
void imEffacer(image * im, pixel couleur)
{

imDessineRect(im,0,0, im->dimx,im->dimy, couleur);

}


// Effectue tout une série de test vérifiant que le module fonctionne et que les
// champ de la structure sont conformes

void imTestRegression()
{
image* im;
pixel couleur;
int i,j;
couleur.r=20;
couleur.b=20;
couleur.g=20;
int dimx,dimy;
dimx=25;
dimy=25;
im=imCreer(dimx,dimy);
assert(im->dimx==25 && im->dimy==25 );
imDetruire(&im);
assert(im->dimx==0 && im->dimy==0);
imDessineRect(im,0,0,10,10,couleur);
  for(i=0;i<10;i++)
    {
        for(j=0;j<10;j++)
        {
        assert(im->tab[i*10+j].b==couleur.b);
        assert(im->tab[i*10+j].r==couleur.r);
        assert(im->tab[i*10+j].g==couleur.g);
        }
    }
imEffacer(im,couleur);
  for(i=0;i<25;i++)
    {
        for(j=0;j<25;j++)
        {
        assert(im->tab[i*10+j].b==couleur.b);
        assert(im->tab[i*10+j].r==couleur.r);
        assert(im->tab[i*10+j].g==couleur.g);
        }
    }


}



void imSauver(const image *pIm, const char filename[])
{
    FILE* f;
	pixel* pix;
	int x,y;

    f = fopen(filename, "w");
    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n", filename);
        assert( f );
    }
    fprintf( f , "P3\n");                           // P3 = ascii avec 3 composantes RVB
    fprintf( f , "%d %d\n", pIm->dimx, pIm->dimy);      // dimension de l'image
    fprintf( f , "255\n");                          // chaque composante est comprise entre 0 et 255

    for(y=0;y<pIm->dimy;++y)
        for(x=0;x<pIm->dimx;++x)
        {
            pix = getpix(*pIm,x++,y);
            fprintf(f, "%d %d %d  ", pix->r, pix->g, pix->b);
        }
    printf("Sauvegarde de l'image %s ...OK\n", filename);
    fclose(f);
}

void imOuvrir(image *pIm, const char filename[])
{
    FILE* f;
	pixel pix;
	int x, y, dimx, dimy;

    f = fopen(filename, "r");
    if (f==NULL)
    {
        printf("Erreur lors de l'ouverture de %s\n", filename);
        assert( f );
    }

    assert( fscanf( f , "P3\n%d %d\n255\n", &dimx, &dimy) ==2 );
    imInit( pIm, dimx, dimy);

    for(y=0;y<pIm->dimy;++y)
        for(x=0;x<pIm->dimx;++x)
        {
            assert( fscanf(f, "%s %s %s  ", &pix.r,  &pix.g,  &pix.b)==3 );
			setPix(pIm,x,y,pix);
        }
    fclose(f);
    printf("Lecture de l'image %s ...OK\n", filename);
}

void imPrintf(const image *pIm)
{
	int x,y;
	pixel *pix;

    printf( "%d %d\n", pIm->dimx, pIm->dimy);      // dimension de l'image

    for(y=0;y<pIm->dimy;++y)
    {
        for(x=0;x<pIm->dimx;++x)
        {
            pix = getpix(*pIm,x,y);
            printf("%d %d %d  ", pix->r, pix->g, pix->b);
        }
        printf("\n");
    }
}


